package org.tech4j.springboot.starter.distributedlock.redisson;

import com.google.common.collect.Maps;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.tech4j.springboot.starter.distributedlock.api.ILock;

import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * @program: tech4j
 * @description:
 * @author: YuKai Fan
 * @create: 2023/2/19 22:34
 **/
public class RedissonLock implements ILock {

    private final RedissonClient redissonClient;

    private final Map<String, RLock> lockMap = Maps.newConcurrentMap();

    public RedissonLock(RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    public RedissonLock(String key, RedissonClient redissonClient) {
        this.redissonClient = redissonClient;
    }

    @Override
    public void lock(String lockKey) {
        RLock lock = getrLock(lockKey);
        lock.lock();
    }

    private RLock getrLock(String lockKey) {
        return lockMap.computeIfAbsent(lockKey, k -> redissonClient.getLock(lockKey));
    }

    private RLock removerLock(String lockKey) {
        return lockMap.remove(lockKey);
    }

    @Override
    public void unlock(String lockKey) {
        RLock lock = removerLock(lockKey);
        lock.unlock();
    }

    @Override
    public void lock(String lockKey, int timeout) {
        RLock lock = getrLock(lockKey);
        lock.lock(timeout, TimeUnit.SECONDS);
    }

    @Override
    public void lock(String lockKey, long timeout, TimeUnit unit) {
        RLock lock = getrLock(lockKey);
        lock.lock(timeout, unit);
    }

    @Override
    public boolean tryLock(String lockKey) {
        RLock lock = getrLock(lockKey);
        return lock.tryLock();
    }

    @Override
    public boolean tryLock(String lockKey, long waitTime, TimeUnit unit) throws InterruptedException {
        RLock lock = getrLock(lockKey);
        return lock.tryLock(waitTime, unit);
    }

    @Override
    public boolean tryLock(String lockKey, long waitTime, long leaseTime, TimeUnit unit) throws InterruptedException {
        RLock lock = getrLock(lockKey);
        return lock.tryLock(waitTime, leaseTime, unit);
    }

    @Override
    public boolean isLocked(String lockKey) {
        RLock lock = getrLock(lockKey);
        return lock.isLocked();
    }

    public RedissonClient getRedissonClient() {
        return redissonClient;
    }
}
